﻿using Kingdee.BOS.Core.DynamicForm;
using Kingdee.BOS.Core.DynamicForm.PlugIn;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;
using Kingdee.BOS.Orm.DataEntity;
using Kingdee.BOS.Util;
using Kingdee.BOS.WebApi.FormService;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RK.Model.Ronma;
using RK.Model;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Kingdee.BOS.Core.Metadata;
using Kingdee.BOS.ServiceHelper;
using Kingdee.BOS;
using Kingdee.BOS.App.Core;
using System.Windows.Interop;
using RK.Tools;

namespace RK.SerivesPlugin.Ronma
{
    [Description("运费采购合同审核时，自动创费用应付单，单据状态为创建状态"), HotUpdate]
    public class ContractToPayable : AbstractOperationServicePlugIn
    {
        public override void BeforeExecuteOperationTransaction(BeforeExecuteOperationTransaction e)
        {
            Context ctx = ObjectUtils.CreateCopy(this.Context) as Context;
            base.BeforeExecuteOperationTransaction(e);
            foreach (var obj in e.SelectedRows.Select(s => s.DataEntity))
            {
                if (obj == null) { return; }
                int F_PXIA_CheckBox = Convert.ToInt32(obj["F_PXIA_CheckBox"]);
                decimal F_POSW_Amount = Convert.ToDecimal(obj["F_POSW_Amount"]);
                //校验运费是否大于0
                //VerfyRunFei(this.OperationResult, F_POSW_Amount, e);
                string payableJson = GetRonmaPayable(obj);
                if (F_PXIA_CheckBox != 1) { return; }
                if (e.Cancel == false)
                {
                    //调用接口，创建费用应付单
                    var apiResult = Api.Save(ctx, "AP_Payable", payableJson);
                    if (apiResult.Result.ResponseStatus.IsSuccess)
                    {
                        WriteLog(apiResult, payableJson);
                        string message = $"同步生成运费费用应付单成功！单号为：{apiResult.Result.Number}";
                        Base.AddOperationResult(this.OperationResult, true, message, MessageType.Normal, "生成运费应付", 0);
                    }
                    else
                    {
                        WriteLog(apiResult, payableJson);
                        string message = "同步生成运费费用应付单失败！错误原因：";
                        foreach (var err in apiResult.Result.ResponseStatus.Errors)
                        {
                            message += $"{err.Message}";
                        }
                        Base.AddOperationResult(this.OperationResult, false, message, MessageType.Normal, "生成运费应付", 0);
                        e.Cancel = true;
                    }
                }
            }
        }

        private void WriteLog(ApiResult apiResult, string payableJson)
        {
            SyncLog log = new SyncLog();
            log.Operation = "创建费用应付单";
            log.FormId = "AP_Payable";
            log.FbillName = "应付单";
            log.FBillNo = apiResult.Result.Number;
            log.Result = JsonConvert.SerializeObject(apiResult);
            log.FOrgId = 0;
            log.Json = payableJson;
            log.IsSuccess = apiResult.Result.ResponseStatus.IsSuccess;
            KingdeeTools.SaveLog(this.Context, log);
        }

        /// <summary>
        /// 获取润马应付单json "RuleId": "AP_PurContractToPayable","STableName": "T_PUR_CONTRACTENTRY",
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        private string GetRonmaPayable(DynamicObject obj)
        {
            string json = "";
            int sBillId = Convert.ToInt32(obj["Id"]);
            string F_POSW_outBillno = Convert.ToString(obj["F_PXIA_SalStockBillno"]);
            decimal F_POSW_Amount = Convert.ToDecimal(obj["F_POSW_Amount"]);
            string conBillNo = obj["BillNo"].ToString();
            DynamicObject CreatorId = obj["CreatorId"] as DynamicObject;
            int creater = CreatorId == null ? 0 : Convert.ToInt32(CreatorId["id"]);

            DateTime cDate = Convert.ToDateTime(obj["date"]);
            string firstDay = cDate.AddDays(1 - cDate.Day).ToString("d");
            string endDay = cDate.AddDays(1 - cDate.Day).AddMonths(1).AddDays(-1).ToString("d");
            DynamicObject SupplierId = obj["SupplierId"] as DynamicObject;
            string supplierNumber = Convert.ToString(SupplierId["Number"]);
            int taxRate = Convert.ToInt32(obj["F_PXIA_Rate"]);
            DynamicObject PurchaseOrgId = obj["PurchaseOrgId"] as DynamicObject;
            string purOrgNumber = Convert.ToString(PurchaseOrgId["Number"]);
            DynamicObjectCollection finObj = obj["ContractFin"] as DynamicObjectCollection;
            DynamicObject sett = finObj[0]["SettleCurrId"] as DynamicObject;
            string currNumber = sett == null ? "PRE001" : sett["Number"].ToString();
            decimal exRate = GetExRate(currNumber, "PRE001", purOrgNumber, firstDay, endDay);
            if (currNumber != "PRE001")
            {
                if (exRate == 1m)
                {
                    throw new Exception("汇率没有提前维护，请确认！");
                }
            }
            string F_PXIA_Text1 = obj["F_PXIA_Text1"].ToString();
            string F_SHDZ = obj["F_SHDZ"].ToString();

            //2、	应付单中的明细-费用项目存在以下可能，当物流服务单上勾选对应复选框时，
            //应付单费用项目匹配（陆运：B3-018-运输费，报关：B3-014-报关费，海运：G1-100-其他应收款-海运费，运报：B2-008-保险费）
            //3、	除海运费外，其他费用自动勾选计入合同履约成本，金额取物流服务单中的含税运费字段，根据出库单数量进行单号匹配行号分配金额
            bool F_LY = Convert.ToBoolean(obj["F_LY"]);//陆运
            bool F_HY = Convert.ToBoolean(obj["F_HY"]);//海运
            bool F_BG = Convert.ToBoolean(obj["F_BG"]);//报关
            bool F_YB = Convert.ToBoolean(obj["F_YB"]);//运报
            string costNumber = GetCostNumber(F_LY, F_HY, F_BG, F_YB);

            Payable payable = new Payable();
            payable.Model = new PayableModel()
            {
                FCreatorId = new Model.Common.GetUserId() { FUserId = creater },
                //FCreatorId = new Model.Common.GetUserId() { FUserId = 100063 },
                F_CPH = F_PXIA_Text1,
                F_SHDZ = F_SHDZ,
                F_POSW_outBillno = F_POSW_outBillno,
                FBillTypeID = new GetNumber() { FNumber = "YFD02_SYS" },
                FDATE = cDate,
                FENDDATE_H = cDate,
                FSUPPLIERID = new GetNumber() { FNumber = supplierNumber },
                FCURRENCYID = new GetNumber() { FNumber = currNumber },
                FPayConditon = new GetNumber() { FNumber = "FKTJ03_SYS" },
                FISPRICEEXCLUDETAX = "true",
                FBUSINESSTYPE = "FY",
                FISTAX = "true",
                FSETTLEORGID = new GetNumber() { FNumber = purOrgNumber },
                FPAYORGID = new GetNumber() { FNumber = purOrgNumber },
                FSetAccountType = "1",
                FCancelStatus = "A",
                FsubHeadFinc = new FsubHeadFinc()
                {
                    FACCNTTIMEJUDGETIME = cDate,
                    FMAINBOOKSTDCURRID = new GetNumber() { FNumber = "PRE001" },
                    FEXCHANGETYPE = new GetNumber() { FNumber = "HLTX01_SYS" },
                    FExchangeRate = exRate,
                    FISCARRIEDDATE = "false",
                },
                FEntityDetail = new List<FEntityDetailItem>(),
            };
            DynamicObjectCollection rows = obj["ContractEntry"] as DynamicObjectCollection;
            var sumQty = rows.Sum(s => Convert.ToDecimal(s["Qty"]));
            var newRows = rows.GroupBy(n => new { FSrcBillNo = Convert.ToString(n["SrcBillNo"]) }).Select(g => new
            {
                FSrcBillNo = g.Key.FSrcBillNo,
                FQty = g.Sum(s => Convert.ToDecimal(s["Qty"])),
                conId = string.Join(",", g.Select(e => Convert.ToString(e[0]))),
                //conId = g.Max(s => Convert.ToInt32(s[0]))
            }).ToList();
            decimal avAmount = 0m;
            for (int i = 0; i < newRows.Count; i++)
            {
                List<LinkItem> links = new List<LinkItem>();
                var ids = newRows[i].conId.Split(',');
                foreach (var id in ids)
                {
                    links.Add(new LinkItem()
                    {
                        FEntityDetail_Link_FRuleId = "AP_PurContractToPayable",
                        FEntityDetail_Link_FSTableName = "T_PUR_CONTRACTENTRY",
                        FEntityDetail_Link_FSBillId = sBillId,
                        FEntityDetail_Link_FSId = Convert.ToInt32(id),
                    });
                }
                List<GetNumber> sNoList = new List<GetNumber>();
                sNoList.Add(new GetNumber() { FNumber = newRows[i].FSrcBillNo });
                var cRow = new FEntityDetailItem();
                cRow.FSourceBillNo = conBillNo;
                cRow.FCOSTID = new GetNumber() { FNumber = costNumber };
                if (newRows.Count > 1)
                {
                    var avPrice = Math.Round(F_POSW_Amount / sumQty * newRows[i].FQty, 10);
                    avAmount += avPrice;
                    if (i == newRows.Count - 1)
                    {
                        avPrice = F_POSW_Amount - avAmount + avPrice;
                        cRow.FTaxPrice = avPrice;
                    }
                    else
                    {
                        cRow.FTaxPrice = avPrice;
                    }
                }
                else
                {
                    cRow.FTaxPrice = F_POSW_Amount;
                }

                cRow.FPriceQty = 1;
                cRow.FINCLUDECOST = false;
                cRow.FEntryTaxRate = taxRate;
                if (!F_HY)
                {
                    cRow.FINCLUDECONTRACTCOMPCOST = true;
                    cRow.FOUTSTOCKID = sNoList;
                }
                else
                {
                    cRow.FCOSTDEPARTMENTID = new GetNumber() { FNumber = "008" };
                }
                cRow.FEntityDetail_Link = links;
                payable.Model.FEntityDetail.Add(cRow);
            }
            json = JsonConvert.SerializeObject(payable);
            return json;
        }

        private decimal GetExRate(string currNumber, string v, string purOrgNumber, string firstDay, string endDay)
        {
            decimal exRate = 1m;
            string formId = "BD_Rate";
            string fieldKeys = "FExchangeRate";
            string filterString = $"FCyToID.fnumber='{v}' AND FCyForID.FNUMBER='{currNumber}' AND FBegDate>='{firstDay}' AND FEndDate<='{endDay}'  AND FDocumentStatus='C' AND FForbidStatus='A'";
            string orderString = "FExchangeRate";
            int limit = 1;
            var res = Api.ExecuteBillQuery(this.Context, formId, fieldKeys, filterString, orderString, limit);
            if (res.Count > 0)
            {
                exRate = Convert.ToDecimal(res.FirstOrDefault().FirstOrDefault());
            }
            return exRate;
        }

        private string GetCostNumber(bool f_LY, bool f_HY, bool f_BG, bool f_YB)
        {
            //（陆运：B3-018-运输费，报关：B3-014-报关费，海运：G1-100-其他应收款-海运费，运报：B2-008-保险费）
            string costNumber = "";
            if (f_LY)
            {
                costNumber = "B3-018";
            }
            if (f_HY)
            {
                costNumber = "G1-100";
            }
            if (f_BG)
            {
                costNumber = "B3-014";
            }
            if (f_YB)
            {
                costNumber = "B2-008";
            }
            return costNumber;
        }

        private void VerfyRunFei(IOperationResult operationResult, decimal f_POSW_Amount, BeforeExecuteOperationTransaction e)
        {
            IOperationResult opResult = new OperationResult();
            if (f_POSW_Amount <= 0)
            {
                opResult.OperateResult.Add(new OperateResult()
                {
                    SuccessStatus = false,
                    Message = $"运费合同，运费必须录入！",
                    MessageType = MessageType.Normal,
                    Name = "运费合同",
                    PKValue = 0,
                });
                operationResult.MergeResult(opResult);
                e.Cancel = true;
            }
        }
        /// <summary>
        /// 加载所有列
        /// </summary>
        /// <param name="e"></param>
        public override void OnPreparePropertys(PreparePropertysEventArgs e)
        {
            base.OnPreparePropertys(e);
            FormMetadata meta = MetaDataServiceHelper.GetFormMetaData(this.Context, this.BusinessInfo.GetForm().Id);
            var fieldKeyList = meta.BusinessInfo.GetBosFields().Select(x => x.Field.Key).ToList();
            for (int i = 0; i < fieldKeyList.Count; i++)
            {
                e.FieldKeys.Add(fieldKeyList[i]);
            }
        }
    }
}
